using DevExpress.Utils;
using DevExpress.Xpo.DB.Helpers;
using DevExpress.XtraEditors;
using DevExpress.XtraGantt;
using DevExpress.XtraGantt.Options; // 确保已引用此命名空间
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Shopfloormanagement
{
    public partial class MPP : DevExpress.XtraEditors.XtraForm
    {

        public static int CurrentPID = 0;
        private bool isDirty = false;//内容变更检测+智能关闭提示使用


        public MPP()
        {
            // 强制英文显示
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            InitializeComponent();
            this.WindowState = FormWindowState.Maximized;
            xtraTabControl1.ShowTabHeader = DevExpress.Utils.DefaultBoolean.False;

        }

        private void MPP_Load(object sender, EventArgs e)
        {
            //载入基本信息
            DataTable dt = LSQL.SQL.ReturnDataTable3(SystemInfo.SQL, "CIP_list", $"delTag=0 and [PID]={CurrentPID} order by ID");
            if (dt.Rows.Count > 0)
            {
                lblTopic.Text = "No."+CurrentPID.ToString()+":"+dt.Rows[0]["Topic"].ToString();

            }





            // 设置甘特图为可编辑模式
            ganttControlMPP.OptionsBehavior.Editable = true;
            ganttControlMPP.OptionsCustomization.AllowModifyTasks = DevExpress.Utils.DefaultBoolean.True;
            ganttControlMPP.OptionsCustomization.AllowModifyDependencies = DevExpress.Utils.DefaultBoolean.True;
            ganttControlMPP.OptionsCustomization.AllowModifyProgress = DevExpress.Utils.DefaultBoolean.True;

            //设置时间尺,最大最小单位
            //ganttControlMPP.OptionsMainTimeRuler.MinUnit = GanttTimescaleUnit.Day;

            //Timeline
            //ganttControlMPP.OptionsTimeline.TimelinePosition = DevExpress.XtraGantt.TimelinePosition.Bottom;


            // 初始化空白的任务列表
            var tasks = new List<GanttTask>();
            var dependencies = new List<GanttDependency>();

            // 计算并更新父节点的时间范围
            UpdateParentTaskDates(tasks);

            // TreeList映射
            ganttControlMPP.TreeListMappings.KeyFieldName = "ID";
            ganttControlMPP.TreeListMappings.ParentFieldName = "ParentID";
            // Chart映
            ganttControlMPP.ChartMappings.StartDateFieldName = "StartTime";
            ganttControlMPP.ChartMappings.FinishDateFieldName = "EndTime";
            ganttControlMPP.ChartMappings.TextFieldName = "Name";
            ganttControlMPP.ChartMappings.ProgressFieldName = "Progress"; // 新增
            ganttControlMPP.DataSource = tasks;

            // 配置依赖映射
            ganttControlMPP.DependencySource = dependencies;
            ganttControlMPP.DependencyMappings.PredecessorFieldName = "PredecessorID";
            ganttControlMPP.DependencyMappings.SuccessorFieldName = "SuccessorID";
            ganttControlMPP.DependencyMappings.TypeFieldName = "Type";

            // 设置字段映射
            ganttControlMPP.Columns.Clear();
            var taskNameColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "Name", Caption = "Task name", Visible = true };
            // 关闭自动列宽
            ganttControlMPP.OptionsView.AutoWidth = false;

            // 设置列宽
            taskNameColumn.MinWidth = 60;
            taskNameColumn.Width = 200;
            ganttControlMPP.Columns.Add(taskNameColumn);

            // 创建Dept列
            var deptColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "Department", Caption = "Dept", Visible = true };
            deptColumn.Width = 50;

            // 创建下拉框编辑器
            var deptCombo = new DevExpress.XtraEditors.Repository.RepositoryItemComboBox();
            DataTable dt1 = LSQL.SQL.ReturnDataTable3(SystemInfo.SQL,"departments", "Del_tag=0 and departmentLevel =4 and isDisplay =1 order by ID");

            if (dt1.Rows.Count > 0)
            {
                string[] deptlist = new string[dt1.Rows.Count];
                for (int i = 0; i < deptlist.Length; i++)
                {
                    deptlist[i] = dt1.Rows[i][1].ToString();
                }

                deptCombo.Items.AddRange(deptlist); // 示例部门
                ganttControlMPP.RepositoryItems.Add(deptCombo);

            }
            // 绑定下拉框到Dept列
            deptColumn.ColumnEdit = deptCombo;
            ganttControlMPP.Columns.Add(deptColumn);
            deptColumn.Width = 80;

            var respColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "Resp", Caption = "Resp", Visible = true };
            respColumn.Width = 50;
            ganttControlMPP.Columns.Add(respColumn);

            var commentsColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "Comments", Caption = "Comments", Visible = true };
            commentsColumn.Width = 120;
            ganttControlMPP.Columns.Add(commentsColumn);

            var startColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "StartTime", Caption = "Start date", Visible = true };
            startColumn.Width = 110;
            startColumn.Format.FormatType = DevExpress.Utils.FormatType.DateTime;
            startColumn.Format.FormatString = "yyyy/MM/dd";
            ganttControlMPP.Columns.Add(startColumn);
            var endColumn = new DevExpress.XtraTreeList.Columns.TreeListColumn() { FieldName = "EndTime", Caption = "End date", Visible = true };
            endColumn.Width = 110;
            endColumn.Format.FormatType = DevExpress.Utils.FormatType.DateTime;
            endColumn.Format.FormatString = "yyyy/MM/dd";
            ganttControlMPP.Columns.Add(endColumn);


            // 设置分割条位置
            ganttControlMPP.SplitterPosition = taskNameColumn.Width+ deptColumn.Width+respColumn.Width+startColumn.Width+endColumn.Width+commentsColumn.Width;

            // 设置列的最小宽度
            foreach (var column in ganttControlMPP.Columns)
            {
                column.MinWidth = 60;
            }
            ganttControlMPP.ExpandAll();

            // 添加右键菜单
            AddContextMenu();

            // 禁止默认右键菜单，只显示自定义菜单
            ganttControlMPP.OptionsMenu.EnableNodeMenu = false;
            ganttControlMPP.OptionsMenu.EnableColumnMenu = false;
            ganttControlMPP.OptionsMenu.EnableFooterMenu = false;

            // 设置单击选中，双击或F2才进入编辑状态
            ganttControlMPP.OptionsBehavior.EditorShowMode = DevExpress.XtraTreeList.TreeListEditorShowMode.MouseUp;
            ganttControlMPP.OptionsBehavior.ImmediateEditor = false;

            // 加载数据库数据
            LoadGanttData(CurrentPID.ToString());
            AddTodayLine();

            //内容变更检测+智能关闭提示
            ganttControlMPP.CellValueChanged += (s, e1) => isDirty = true;

            // 关闭 DevExpress GanttControl 的自动调度（Automatic Scheduling）
            //ganttControlMPP.OptionsBehavior.ScheduleMode = ScheduleMode.Manual;
        }

        /// <summary>
        /// 清空所有数据
        /// </summary>
        private void ClearAllData()
        {
            if (MessageBox.Show("Are you sure you want to clear all data?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                var tasks = new List<GanttTask>();
                var dependencies = new List<GanttDependency>();
                
                ganttControlMPP.DataSource = tasks;
                ganttControlMPP.DependencySource = dependencies;
                ganttControlMPP.RefreshDataSource();
                
                MessageBox.Show("Data has been cleared", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        /// <summary>
        /// 通过右键菜单调整层级关系
        /// </summary>
        private void AddContextMenu()
        {
            var contextMenu = new ContextMenuStrip();
            
            // 添加任务
            var addTaskItem = new ToolStripMenuItem("Add Project");
            addTaskItem.Click += (s, e) => AddNewTask();
            contextMenu.Items.Add(addTaskItem);
            contextMenu.Items.Add(new ToolStripSeparator());
            
            // 添加子任务
            var addChildItem = new ToolStripMenuItem("Add Subtask");
            addChildItem.Click += (s, e) => AddChildTask();
            contextMenu.Items.Add(addChildItem);
            
            // 移动到父级
            var moveToParentItem = new ToolStripMenuItem("Move to Parent");
            moveToParentItem.Click += (s, e) => MoveToParent();
            contextMenu.Items.Add(moveToParentItem);
            
            // 移动到根级
            var moveToRootItem = new ToolStripMenuItem("Move to Root");
            moveToRootItem.Click += (s, e) => MoveToRoot();
            contextMenu.Items.Add(moveToRootItem);
            
            contextMenu.Items.Add(new ToolStripSeparator());
            
            // 设置父任务
            var setParentItem = new ToolStripMenuItem("Set Parent Task");
            setParentItem.Click += (s, e) => SetParentTask();
            contextMenu.Items.Add(setParentItem);
            
            contextMenu.Items.Add(new ToolStripSeparator());
            
            // 删除任务
            var deleteItem = new ToolStripMenuItem("Delete Task");
            deleteItem.Click += (s, e) => DeleteSelectedTask();
            contextMenu.Items.Add(deleteItem);
            
            // 绑定右键菜单
            ganttControlMPP.ContextMenuStrip = contextMenu;
        }

        /// <summary>
        /// 添加子任务
        /// </summary>
        private void AddChildTask()
        {
            var selectedNode = ganttControlMPP.FocusedNode;
            if (selectedNode == null)
            {
                MessageBox.Show("Please select a task first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
            var parentTask = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.GetValue("ID"));
            
            var newTask = new GanttTask
            {
                ID = tasks.Count > 0 ? tasks.Max(t => t.ID) + 1 : 1,
                ParentID = parentTask.ID,
                Name = $"子任务 {parentTask.Name}",
                StartTime = DateTime.Today,
                EndTime = DateTime.Today.AddDays(7),
                Progress = 0,
                Resp = "",
                Department = "",
                Comments = ""
            };
            
            tasks.Add(newTask);
            UpdateParentTaskDates(tasks);
            ganttControlMPP.RefreshDataSource();
            ganttControlMPP.ExpandAll();
        }

        /// <summary>
        /// 移动到父级
        /// </summary>
        private void MoveToParent()
        {
            var selectedNode = ganttControlMPP.FocusedNode;
            if (selectedNode?.ParentNode == null)
            {
                MessageBox.Show("The current task is already a root-level task", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
            var currentTask = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.GetValue("ID"));
            var parentTask = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.ParentNode.GetValue("ID"));
            
            if (currentTask != null && parentTask != null)
            {
                currentTask.ParentID = parentTask.ParentID;
                UpdateParentTaskDates(tasks);
                ganttControlMPP.RefreshDataSource();
                ganttControlMPP.ExpandAll();
            }
        }

        /// <summary>
        /// 移动到根级
        /// </summary>
        private void MoveToRoot()
        {
            var selectedNode = ganttControlMPP.FocusedNode;
            if (selectedNode?.ParentNode == null)
            {
                MessageBox.Show("The current task is already a root-level task", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
            var currentTask = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.GetValue("ID"));
            
            if (currentTask != null)
            {
                currentTask.ParentID = null;
                UpdateParentTaskDates(tasks);
                ganttControlMPP.RefreshDataSource();
                ganttControlMPP.ExpandAll();
            }
        }

        /// <summary>
        /// 删除选中的任务
        /// </summary>
        private void DeleteSelectedTask()
        {
            var selectedNode = ganttControlMPP.FocusedNode;
            if (selectedNode == null)
            {
                MessageBox.Show("Please select a task first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (MessageBox.Show("Are you sure you want to delete this task? Its subtasks will also be deleted.", "Confirm Deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
                var taskToDelete = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.GetValue("ID"));
                
                if (taskToDelete != null)
                {
                    // 删除所有子任务
                    var tasksToRemove = GetDescendantTasks(tasks, taskToDelete.ID);
                    tasksToRemove.Add(taskToDelete);
                    
                    foreach (var task in tasksToRemove)
                    {
                        tasks.Remove(task);
                    }
                    
                    UpdateParentTaskDates(tasks);
                    ganttControlMPP.RefreshDataSource();
                    ganttControlMPP.ExpandAll();
                }
            }
        }

        /// <summary>
        /// 获取指定任务的所有后代任务
        /// </summary>
        private List<GanttTask> GetDescendantTasks(List<GanttTask> tasks, int parentId)
        {
            var descendants = new List<GanttTask>();
            var children = tasks.Where(t => t.ParentID == parentId).ToList();
            
            foreach (var child in children)
            {
                descendants.Add(child);
                descendants.AddRange(GetDescendantTasks(tasks, child.ID));
            }
            
            return descendants;
        }

        /// <summary>
        /// 设置父任务
        /// </summary>
        private void SetParentTask()
        {
            var selectedNode = ganttControlMPP.FocusedNode;
            if (selectedNode == null)
            {
                MessageBox.Show("Please select a task first", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
            var currentTask = tasks.FirstOrDefault(t => t.ID == (int)selectedNode.GetValue("ID"));
            if (currentTask == null) return;

            // 过滤掉自己和所有后代节点，防止循环
            var invalidIds = GetDescendantTasks(tasks, currentTask.ID).Select(t => t.ID).ToHashSet();
            invalidIds.Add(currentTask.ID);

            var parentTasks = tasks.Where(t => !invalidIds.Contains(t.ID)).ToList();
            if (parentTasks.Count == 0)
            {
                MessageBox.Show("No other tasks can be used as parent tasks", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 弹出选择对话框
            using (var form = new Form())
            {
                form.Text = "Select Parent Task";
                form.Width = 300;
                form.Height = 200;
                var listBox = new ListBox { Dock = DockStyle.Fill };
                listBox.DataSource = parentTasks;
                listBox.DisplayMember = "Name";
                listBox.ValueMember = "ID";
                form.Controls.Add(listBox);

                var btnOk = new Button { Text = "OK", Dock = DockStyle.Bottom };
                btnOk.Click += (s, e) => form.DialogResult = DialogResult.OK;
                form.Controls.Add(btnOk);

                if (form.ShowDialog() == DialogResult.OK && listBox.SelectedItem is GanttTask parentTask)
                {
                    currentTask.ParentID = parentTask.ID;
                    UpdateParentTaskDates(tasks);
                    ganttControlMPP.RefreshDataSource();
                    ganttControlMPP.ExpandAll();
                    MessageBox.Show($"Task '{currentTask.Name}' has been set as a subtask of '{parentTask.Name}'", "Setting Successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }


        /// <summary>
        /// 添加新任务
        /// </summary>
        private void AddNewTask()
        {
            try
            {
                var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
                var newTask = new GanttTask
                {
                    ID = tasks.Count > 0 ? tasks.Max(t => t.ID) + 1 : 1,
                    Name = "New Task",
                    StartTime = DateTime.Today,
                    EndTime = DateTime.Today.AddDays(7),
                    Progress = 0,
                    Resp = "",
                    Department = "",
                    Comments = ""
                };
                
                tasks.Add(newTask);
                ganttControlMPP.RefreshDataSource();
                ganttControlMPP.ExpandAll();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Failed to add task: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 更新父节点的时间范围，使其等于所有子节点的时间范围之和
        /// </summary>
        /// <param name="tasks">任务列表</param>
        private void UpdateParentTaskDates(List<GanttTask> tasks)
        {
            // 按父节点ID分组，计算每个父节点的子节点时间范围
            var parentGroups = tasks.Where(t => t.ParentID.HasValue)
                                   .GroupBy(t => t.ParentID.Value)
                                   .ToDictionary(g => g.Key, g => g.ToList());

            // 更新每个父节点的时间范围
            foreach (var parentGroup in parentGroups)
            {
                var parentTask = tasks.FirstOrDefault(t => t.ID == parentGroup.Key);
                if (parentTask != null)
                {
                    var childTasks = parentGroup.Value;
                    
                    // 计算子节点的最早开始时间和最晚结束时间
                    var minStartDate = childTasks.Min(t => t.StartTime);
                    var maxEndDate = childTasks.Max(t => t.EndTime);
                    
                    // 更新父节点的时间范围
                    parentTask.StartTime = minStartDate;
                    parentTask.EndTime = maxEndDate;
                }
            }

            // 递归更新更高层级的父节点
            var topLevelParents = tasks.Where(t => t.ParentID.HasValue && 
                                                  !tasks.Any(p => p.ID == t.ParentID.Value && p.ParentID.HasValue))
                                     .Select(t => t.ParentID.Value)
                                     .Distinct()
                                     .ToList();

            foreach (var topParentId in topLevelParents)
            {
                UpdateParentTaskDatesRecursive(tasks, topParentId);
            }
        }

        /// <summary>
        /// 递归更新父节点的时间范围
        /// </summary>
        /// <param name="tasks">任务列表</param>
        /// <param name="parentId">父节点ID</param>
        private void UpdateParentTaskDatesRecursive(List<GanttTask> tasks, int parentId)
        {
            var parentTask = tasks.FirstOrDefault(t => t.ID == parentId);
            if (parentTask == null) return;

            var childTasks = tasks.Where(t => t.ParentID == parentId).ToList();
            if (childTasks.Count == 0) return;

            // 计算子节点的最早开始时间和最晚结束时间
            var minStartDate = childTasks.Min(t => t.StartTime);
            var maxEndDate = childTasks.Max(t => t.EndTime);

            // 更新父节点的时间范围
            parentTask.StartTime = minStartDate;
            parentTask.EndTime = maxEndDate;

            // 递归更新更高层级的父节点
            if (parentTask.ParentID.HasValue)
            {
                UpdateParentTaskDatesRecursive(tasks, parentTask.ParentID.Value);
            }
        }

        // 请将此连接字符串替换为您的实际数据库连接信息
        private string connectionString = SystemInfo.SQL;

        // 加载任务
        public List<GanttTask> LoadTasks(string pid)
        {
            var tasks = new List<GanttTask>();
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = "SELECT * FROM CIP_MPPTask WHERE PID = @PID AND (delTag=0 OR delTag IS NULL)";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@PID", pid);
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            tasks.Add(new GanttTask
                            {
                                ID = (int)reader["TaskID"],
                                ParentID = reader["ParentID"] as int?,
                                Name = reader["Name"].ToString(),
                                Department = reader["Department"].ToString(),
                                Resp = reader["Resp"].ToString(),
                                StartTime = reader["StartTime"] as DateTime? ?? DateTime.MinValue,
                                EndTime = reader["EndTime"] as DateTime? ?? DateTime.MinValue,
                                Duration = TimeSpan.FromHours(Convert.ToDouble(reader["Duration"])),
                                Progress = reader["Progress"] as double? ?? 0,
                                Status = reader["Status"] as int? ?? 0,
                                Comments = reader["Comments"].ToString(),
                                ConstraintType = reader["ConstraintType"] as int?,
                                ConstraintDate = reader["ConstraintDate"] as DateTime?
                            });
                        }
                    }
                }
            }
            return tasks;
        }

        // 新增任务
        public void AddTask(GanttTask task, string pid)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                // 开启IDENTITY_INSERT
                using (var cmd = new SqlCommand("SET IDENTITY_INSERT CIP_MPPTask ON", conn))
                {
                    cmd.ExecuteNonQuery();
                }

                string sql = @"INSERT INTO CIP_MPPTask 
    (PID, ParentID, Name, Department, Resp, StartTime, EndTime, Duration, Progress, Status, Comments, ConstraintType, ConstraintDate, delTag)
    VALUES (@PID, NULL, @Name, @Department, @Resp, @StartTime, @EndTime, @Duration, @Progress, @Status, @Comments, @ConstraintType, @ConstraintDate, 0)";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@PID", pid);
                    cmd.Parameters.AddWithValue("@ParentID", (object)task.ParentID ?? DBNull.Value);
                    cmd.Parameters.AddWithValue("@Name", task.Name ?? "");
                    cmd.Parameters.AddWithValue("@Department", task.Department ?? "");
                    cmd.Parameters.AddWithValue("@Resp", task.Resp ?? "");
                    cmd.Parameters.AddWithValue("@StartTime", task.StartTime);
                    cmd.Parameters.AddWithValue("@EndTime", task.EndTime);
                    cmd.Parameters.AddWithValue("@Duration", task.Duration.TotalHours);
                    cmd.Parameters.AddWithValue("@Progress", task.Progress);
                    cmd.Parameters.AddWithValue("@Status", task.Status);
                    cmd.Parameters.AddWithValue("@Comments", task.Comments ?? "");
                    cmd.Parameters.AddWithValue("@ConstraintType", (object)task.ConstraintType ?? DBNull.Value);
                    cmd.Parameters.AddWithValue("@ConstraintDate", (object)task.ConstraintDate ?? DBNull.Value);
                    cmd.ExecuteNonQuery();
                }

                // 关闭IDENTITY_INSERT
                using (var cmd = new SqlCommand("SET IDENTITY_INSERT CIP_MPPTask OFF", conn))
                {
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // 更新任务
        public void UpdateTask(GanttTask task)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = @"UPDATE CIP_MPPTask SET 
                    ParentID=@ParentID, Name=@Name, Department=@Department, Resp=@Resp, StartTime=@StartTime, EndTime=@EndTime, 
                    Duration=@Duration, Progress=@Progress, Status=@Status, Comments=@Comments, ConstraintType=@ConstraintType, ConstraintDate=@ConstraintDate
                    WHERE TaskID=@TaskID";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@TaskID", task.ID);
                    cmd.Parameters.AddWithValue("@ParentID", (object)task.ParentID ?? DBNull.Value);
                    cmd.Parameters.AddWithValue("@Name", task.Name ?? "");
                    cmd.Parameters.AddWithValue("@Department", task.Department ?? "");
                    cmd.Parameters.AddWithValue("@Resp", task.Resp ?? "");
                    cmd.Parameters.AddWithValue("@StartTime", task.StartTime);
                    cmd.Parameters.AddWithValue("@EndTime", task.EndTime);
                    cmd.Parameters.AddWithValue("@Duration", task.Duration.TotalHours);
                    cmd.Parameters.AddWithValue("@Progress", task.Progress);
                    cmd.Parameters.AddWithValue("@Status", task.Status);
                    cmd.Parameters.AddWithValue("@Comments", task.Comments ?? "");
                    cmd.Parameters.AddWithValue("@ConstraintType", (object)task.ConstraintType ?? DBNull.Value);
                    cmd.Parameters.AddWithValue("@ConstraintDate", (object)task.ConstraintDate ?? DBNull.Value);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // 删除任务（及其依赖）
        public void DeleteTask(int taskId)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                // 先逻辑删除依赖
                string delDep = "UPDATE CIP_MPPDependency SET delTag=1 WHERE TaskID=@TaskID OR PredecessorID=@TaskID";
                using (var cmd = new SqlCommand(delDep, conn))
                {
                    cmd.Parameters.AddWithValue("@TaskID", taskId);
                    cmd.ExecuteNonQuery();
                }
                // 逻辑删除任务
                string delTask = "UPDATE CIP_MPPTask SET delTag=1 WHERE TaskID=@TaskID";
                using (var cmd = new SqlCommand(delTask, conn))
                {
                    cmd.Parameters.AddWithValue("@TaskID", taskId);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // 加载依赖
        public List<GanttDependency> LoadDependencies(string pid)
        {
            var deps = new List<GanttDependency>();
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = @"SELECT * FROM CIP_MPPDependency WHERE PID = @PID";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@PID", pid);
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            deps.Add(new GanttDependency
                            {
                                ID = (int)reader["DependencyID"],
                                PredecessorID = (int)reader["PredecessorID"],
                                SuccessorID = (int)reader["TaskID"],
                                Type = reader["Type"] as int? ?? 0,
                                PID = reader["PID"] as int? ?? 0 // 新增
                            });
                        }
                    }
                }
            }
            return deps;
        }

        // 新增依赖
        public void AddDependency(GanttDependency dep)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = @"INSERT INTO CIP_MPPDependency (DependencyID, TaskID, PredecessorID, Type, PID)
                               VALUES (@DependencyID, @TaskID, @PredecessorID, @Type, @PID)";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@DependencyID", dep.ID);
                    cmd.Parameters.AddWithValue("@TaskID", dep.SuccessorID);
                    cmd.Parameters.AddWithValue("@PredecessorID", dep.PredecessorID);
                    cmd.Parameters.AddWithValue("@Type", dep.Type);
                    cmd.Parameters.AddWithValue("@PID", dep.PID);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        // 删除依赖
        public void DeleteDependency(int dependencyId)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = "DELETE FROM CIP_MPPDependency WHERE DependencyID=@DependencyID";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@DependencyID", dependencyId);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        public void DeleteDependenciesByPID(int pid)
        {
            using (var conn = new SqlConnection(connectionString))
            {
                conn.Open();
                string sql = "DELETE FROM CIP_MPPDependency WHERE PID=@PID";
                using (var cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@PID", pid);
                    cmd.ExecuteNonQuery();
                }
            }
        }

        private void LoadGanttData(string pid)
        {
            var tasks = LoadTasks(pid);
            var dependencies = LoadDependencies(pid);

            if (tasks == null || tasks.Count == 0)
            {
                tasks = new List<GanttTask>();
                dependencies = new List<GanttDependency>();
            }

            ganttControlMPP.DataSource = tasks;
            ganttControlMPP.DependencySource = dependencies;
            UpdateParentTaskDates(tasks);
            ganttControlMPP.RefreshDataSource();
            ganttControlMPP.ExpandAll();
        }

        public void SaveGanttData(string pid)
        {
            try
            {
                var tasks = (List<GanttTask>)ganttControlMPP.DataSource;
                var dependencies = (List<GanttDependency>)ganttControlMPP.DependencySource;

                // 1. 先逻辑删除该项目下所有任务和依赖
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    // 逻辑删除依赖
                    string delDep = @"UPDATE d SET delTag=1 FROM CIP_MPPDependency d
                                      INNER JOIN CIP_MPPTask t ON d.TaskID = t.TaskID
                                      WHERE t.PID = @PID";
                    using (var cmd = new SqlCommand(delDep, conn))
                    {
                        cmd.Parameters.AddWithValue("@PID", pid);
                        cmd.ExecuteNonQuery();
                    }
                    // 逻辑删除任务
                    string delTask = "UPDATE CIP_MPPTask SET delTag=1 WHERE PID = @PID";
                    using (var cmd = new SqlCommand(delTask, conn))
                    {
                        cmd.Parameters.AddWithValue("@PID", pid);
                        cmd.ExecuteNonQuery();
                    }
                }

                // 2. 建立原ID到新ID的映射
                var idMap = new Dictionary<int, int>();
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    // 先插入所有任务，获取新ID
                    foreach (var task in tasks)
                    {
                        string sql = @"INSERT INTO CIP_MPPTask 
                    (PID, ParentID, Name, Department, Resp, StartTime, EndTime, Duration, Progress, Status, Comments, ConstraintType, ConstraintDate, delTag)
                    VALUES (@PID, NULL, @Name, @Department, @Resp, @StartTime, @EndTime, @Duration, @Progress, @Status, @Comments, @ConstraintType, @ConstraintDate, 0);
                    SELECT SCOPE_IDENTITY();";
                        using (var cmd = new SqlCommand(sql, conn))
                        {
                            cmd.Parameters.AddWithValue("@PID", pid);
                            cmd.Parameters.AddWithValue("@Name", task.Name ?? "");
                            cmd.Parameters.AddWithValue("@Department", task.Department ?? "");
                            cmd.Parameters.AddWithValue("@Resp", task.Resp ?? "");
                            cmd.Parameters.AddWithValue("@StartTime", task.StartTime);
                            cmd.Parameters.AddWithValue("@EndTime", task.EndTime);
                            cmd.Parameters.AddWithValue("@Duration", task.Duration.TotalHours);
                            cmd.Parameters.AddWithValue("@Progress", task.Progress);
                            cmd.Parameters.AddWithValue("@Status", task.Status);
                            cmd.Parameters.AddWithValue("@Comments", task.Comments ?? "");
                            cmd.Parameters.AddWithValue("@ConstraintType", (object)task.ConstraintType ?? DBNull.Value);
                            cmd.Parameters.AddWithValue("@ConstraintDate", (object)task.ConstraintDate ?? DBNull.Value);
                            int newId = Convert.ToInt32(cmd.ExecuteScalar());
                            idMap[task.ID] = newId;
                        }
                    }
                }

                // 3. 再遍历所有任务，更新ParentID为新ID
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    foreach (var task in tasks)
                    {
                        if (task.ParentID.HasValue && idMap.ContainsKey(task.ParentID.Value))
                        {
                            int newTaskId = idMap[task.ID];
                            int newParentId = idMap[task.ParentID.Value];
                            string sql = "UPDATE CIP_MPPTask SET ParentID=@ParentID WHERE TaskID=@TaskID";
                            using (var cmd = new SqlCommand(sql, conn))
                            {
                                cmd.Parameters.AddWithValue("@ParentID", newParentId);
                                cmd.Parameters.AddWithValue("@TaskID", newTaskId);
                                cmd.ExecuteNonQuery();
                            }
                        }
                    }
                }

                // 4. 插入依赖时，也用新ID替换PredecessorID和SuccessorID
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    foreach (var dep in dependencies)
                    {
                        if (idMap.ContainsKey(dep.PredecessorID) && idMap.ContainsKey(dep.SuccessorID))
                        {
                            string sql = @"INSERT INTO CIP_MPPDependency (TaskID, PredecessorID, Type, delTag, PID)
                                   VALUES (@TaskID, @PredecessorID, @Type, 0, @PID)";
                            using (var cmd = new SqlCommand(sql, conn))
                            {
                                cmd.Parameters.AddWithValue("@TaskID", idMap[dep.SuccessorID]);
                                cmd.Parameters.AddWithValue("@PredecessorID", idMap[dep.PredecessorID]);
                                cmd.Parameters.AddWithValue("@Type", dep.Type);
                                cmd.Parameters.AddWithValue("@PID", int.Parse(pid)); // 这里pid是string，需转int
                                cmd.ExecuteNonQuery();
                            }
                        }
                    }
                }

                MessageBox.Show("Data has been saved to the database", "Save Successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Failed to save: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveGanttData(CurrentPID.ToString());
            isDirty = false;
        }

        private void AddTodayLine()
        {
            ganttControlMPP.CustomDrawTimescaleColumn += GanttControlMPP_CustomDrawTimescaleColumn;
            ganttControlMPP.CustomDrawTask += GanttControlMPP_CustomDrawTask;
        }

        private void GanttControlMPP_CustomDrawTimescaleColumn(object sender, DevExpress.XtraGantt.CustomDrawTimescaleColumnEventArgs e)
        {
            DateTime today = DateTime.Today;
            var column = e.Column;

            // 只在“天”级别的列填充
            if ((column.FinishDate - column.StartDate).TotalDays == 1 &&
                column.StartDate <= today && column.FinishDate > today)
            {
                e.DrawBackground();

                // 整列填充浅红色
                RectangleF fillRect = new RectangleF(
                    (float)e.GetPosition(column.StartDate),
                    column.Bounds.Y,
                    (float)(e.GetPosition(column.FinishDate) - e.GetPosition(column.StartDate)),
                    column.Bounds.Height
                );
                e.Cache.FillRectangle(System.Drawing.Color.MistyRose, fillRect); // 你也可以用Color.LightCoral等

                e.DrawHeader();
                e.Handled = true;
            }
        }

        private void GanttControlMPP_CustomDrawTask(object sender, DevExpress.XtraGantt.CustomDrawTaskEventArgs e)
        {
                // 设置浅蓝色
                System.Drawing.Color lightBlue = System.Drawing.Color.FromArgb(68, 114, 196); // 浅蓝色
                e.Appearance.BackColor = lightBlue;
                e.Appearance.BackColor2 = lightBlue;
                e.Appearance.BorderColor = lightBlue;

        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (isDirty)
            {
                DialogResult result = MessageBox.Show("Do you want to save changes?", "Confirm", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    // 用户点击 "是"，调用 ButtonSave_Click 方法
                    btnSave_Click(null, EventArgs.Empty);
                    this.Close();
                }
                else if (result == DialogResult.No)
                {
                    // 用户选择 "否"
                    MessageBox.Show("Not saved!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    this.Close();
                }

            }
            else
            {
                this.Close();
            }
        }

        private void MPP_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isDirty)
            {
                DialogResult result = MessageBox.Show("Do you want to save changes?", "Confirm", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    btnSave_Click(null, EventArgs.Empty);
                    // 允许关闭
                }
                else if (result == DialogResult.No)
                {
                    MessageBox.Show("Not saved!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    // 允许关闭
                }
                else
                {
                    // 取消关闭
                    e.Cancel = true;
                }
            }
            // isDirty为false时，直接关闭
        }
    }

    public class GanttTask
    {
        // 层级关系
        public int ID { get; set; }
        public int? ParentID { get; set; }

        // 基本信息
        public string Name { get; set; }                // 任务名称
        public DateTime StartTime { get; set; }         // 开始时间
        public DateTime EndTime { get; set; }           // 结束时间
        public TimeSpan Duration { get; set; }          // 持续时间
        public double Progress { get; set; }            // 进度（0~1）

        public int Status { get; set; } //状态 0,1,2,3,4  代表0%，25%，50%，75%，100%

        // 负责人
        public string Resp { get; set; }
        public string Department { get; set; }
        public string Comments { get; set; } // 备注

        // 依赖关系
        public List<int> PredecessorIDs { get; set; }   // 前置任务ID列表

        // 约束相关（预留）
        public int? ConstraintType { get; set; }        // 约束类型
        public DateTime? ConstraintDate { get; set; }   // 约束日期
    }

    public class GanttDependency
    {
        public int ID { get; set; }
        public int PredecessorID { get; set; }
        public int SuccessorID { get; set; }
        public int Type { get; set; } = 0; // 0=FinishToStart
        public int PID { get; set; } // 新增
    }
}